<?php

/**
 * 文件柜模块
 *
 * @link http://www.ibos.com.cn/
 * @copyright Copyright &copy; 2008-2013 IBOS Inc
 * @author gzhzh <gzhzh@ibos.com.cn>
 */

/**
 * 文件柜模块------  检测工具类
 * @package application.modules.file.util
 * @version $Id: FileCheck.php 3297 2014-06-19 09:40:54Z gzhzh $
 * @author gzhzh <gzhzh@ibos.com.cn>
 */

namespace application\modules\file\utils;

use application\core\utils\IBOS;
use application\core\utils\StringUtil;
use application\core\utils\System;
use application\modules\file\model\File;
use application\modules\file\model\FileDirAccess;
use application\modules\file\model\FileShare;
use application\modules\user\model\User;

class FileCheck extends System {

	const NONE_ACCESS = 0; // 无权限
	const READABLED = 1; // 只读
	const WRITEABLED = 2; // 读写

	public static function getInstance( $className = __CLASS__ ) {
		return parent::getInstance( $className );
	}

	/**
	 * 检查一个文件是否属于某个人
	 * @param integer $fid 文件id
	 * @param integer $uid 用户id
	 * @return boolean
	 */
	public function isOwn( $fid, $uid ) {
		$record = File::model()->fetch( "`fid` = {$fid} AND `uid` = {$uid}" );
		return !empty( $record );
	}

	/**
	 * 检测是否存在同名文件或文件夹
	 * @param string $name 文件/文件夹名
	 * @param integer $pid 父级id
	 * @param integer $uid 用户id
	 * @param integer $belong 类型，0个人，1公司
	 * @return boolean
	 */
	public function isExist( $name, $pid, $uid, $cloudid, $belong = 0 ) {
		$name = htmlspecialchars( strtolower( $name ) );
		$pid = intval( $pid );
		$uid = intval( $uid );
		$record = File::model()->fetch( "`name` = '{$name}' AND `pid` = {$pid} AND `uid` = {$uid} AND `isdel` = 0 AND `cloudid` = {$cloudid} AND `belong`={$belong}" );
		return !empty( $record );
	}

	/**
	 * 检测阅读权限
	 * @param integer $fid 文件id
	 * @param integer $uid 用户id
	 * @return boolean
	 */
	public function isReadable( $fid, $uid ) {
		$fid = intval( $fid );
		$uid = intval( $uid );
		$user = User::model()->fetchByUid( $uid );
		if ( !$fid || !$user ) {
			return false;
		}
		$file = File::model()->fetchWithShare( $fid );
		if ( $file['belong'] == File::BELONG_COMPANY ) { // 公司网盘
			$access = FileDirAccess::model()->fetchByAttributes( array( 'fid' => $fid ) );
			return $this->getAccess( $access, $uid ) !== self::NONE_ACCESS;
		} else {
			if ( $user['uid'] == $file['uid'] ) {
				return true;
			}
			$isShare = $this->hasUserAccess( array(
				'u' => $file['touids'],
				'd' => $file['todeptids'],
				'p' => $file['toposids']
					), $user );
			if ( $isShare ) {
				return true;
			}
			if ( $file['pid'] != 0 ) { // 特殊情况，某个共享文件夹里面的文件或文件夹
				$findPid = str_replace( '/', ',', trim(
								str_replace( '/0/', '', $file['idpath'] )
								, '/' ) );
				$sqlStr = "FIND_IN_SET({$uid}, fs.`touids`)";
				$deptIdArr = explode( ",", $user['alldeptid'] . ',alldept' );
				foreach ( $deptIdArr as $deptid ) {
					if ( $deptid != '' ) {
						$sqlStr .= " OR FIND_IN_SET( '{$deptid}', fs.`todeptids`) ";
					}
				}
				$posIdArr = explode( ",", $user['allposid'] );
				foreach ( $posIdArr as $posid ) {
					if ( $posid !== '' ) {
						$sqlStr .= " OR FIND_IN_SET( '{$posid}', fs.`toposids`) ";
					}
				}
				$record = IBOS::app()->db->createCommand()
						->select( "*,f.fid AS fid" )
						->from( "{{file_share}} as fs" )
						->leftJoin( "{{file}} f", "f.`fid` = fs.`fid`" )
						->where( sprintf( "FIND_IN_SET(f.`fid`, '%s') AND (%s)", $findPid, $sqlStr ) );
				return !empty( $record );
			}
		}
	}

	/**
	 * 获取用户对某个文件/文件夹的权限（针对公司网盘）
	 * @param array $access 文件权限数据(由file_dir_access表记录)
	 * @param integer $uid 用户id
	 * @return integer
	 */
	public function getAccess( $access, $uid ) {
		if ( empty( $access ) ) {
			return self::WRITEABLED;
		}
		if ( empty( $access['wdeptids'] ) && empty( $access['wposids'] ) && empty( $access['wuids'] ) && empty( $access['rdeptids'] ) && empty( $access['rposids'] ) && empty( $access['ruids'] ) ) {
			return self::WRITEABLED;
		}
		$user = User::model()->fetchByUid( $uid );
		$hasWrite = $this->hasUserAccess( array(
			'u' => $access['wuids'],
			'p' => $access['wposids'],
			'd' => $access['wdeptids']
				), $user );
		if ( $hasWrite || $this->isManager( $uid ) ) {
			return self::WRITEABLED;
		}
		$hasRead = $this->hasUserAccess( array(
			'u' => $access['ruids'],
			'p' => $access['rposids'],
			'd' => $access['rdeptids']
				), $user );
		if ( $hasRead ) {
			return self::READABLED;
		}
		return self::NONE_ACCESS;
	}

	/**
	 * 判断某个uid是否公司网盘管理员
	 * @param integer $uid 用户uid
	 * @return boolean
	 */
	public function isManager( $uid ) {
		if ( IBOS::app()->user->isadministrator ) {
			return true;
		}
		$manager = IBOS::app()->setting->get( 'setting/filecompmanager' );
		if ( empty( $manager ) ) {
			return false;
		}
		$user = User::model()->fetchByUid( $uid );
		$isManager = $this->hasUserAccess( array(
			'u' => $manager['uid'],
			'p' => $manager['positionid'],
			'd' => $manager['deptid']
				), $user );
		if ( $isManager ) {
			return true;
		}
		return false;
	}

	/**
	 * 检查某个文件/文件夹是否已共享
	 * @param integer $fid 文件/文件夹id 
	 * @return boolean
	 */
	public function isShare( $fid ) {
		$record = FileShare::model()->fetch( sprintf( "fid=%d", intval( $fid ) ) );
		return !empty( $record );
	}

	/**
	 * 判断用户哪个维度有权限
	 * @param array $compare 用作对比的一维数组,格式：array('u'=>'','p'=>'','d'=>''))
	 * @param array $user 用户数组
	 * @return boolean
	 */
	protected function hasUserAccess( $compare, $user ) {
		if ( $this->findIn( $compare['u'], $user['uid'] ) ) {
			return true;
		}
		if ( $this->findIn( $compare['p'], $user['allposid'] ) ) {
			return true;
		}
		if ( $this->findIn( $compare['d'], $user['alldeptid'] . ',alldept' ) ) {
			return true;
		}
		return false;
	}

	/**
	 * 查找是否包含在内,两边都可以是英文逗号相连的字符串
	 * @param string $strId 目标范围
	 * @param  string $id 所有值
	 * @return boolean
	 */
	protected function findIn( $strId, $id ) {
		return StringUtil::findIn( $strId, $id );
	}

}
